<?php

namespace backend\controllers;

use yii\web\Controller;
use backend\models\RoleForm;
use backend\models\TauRoleinfo;
use yii\base\Exception;
use backend\models\AuthItem;
use backend\models\AuthItemChild;
use yii\web\ForbiddenHttpException;
use yii\db\Query;
use backend\models\TauOperinfo;
use backend\models\AuthAssignment;

/**
 * #name=rbac操作模块#
 * 
 */
class RbacController extends Controller {
	public $layout='ace';
	public $enableCsrfValidation = false;//yii 2 局部关闭 CSRF 拦截
	
	//前置过滤器
	  public function beforeAction($action){
		if(parent::beforeAction($action)){
			 //判断是否登录，没有登录直接跳转到登录页面
			if(\Yii::$app->user->isGuest){
				$this->redirect(['main/login']);
				
			}			
			 if(!\Yii::$app->user->isGuest){
				$controllerName=$this->id;//获取控制器名字
				$actionName=$action->id;//获取操作名称
				$permissionName=$controllerName."_".$actionName;
				if(\Yii::$app->user->can($permissionName)){
					return true;
				}else{
					throw new ForbiddenHttpException('你没有权限访问该模块');
				}
			}  
		}else{
			return false;
		}
	}  
	/**
	 * #operation=增加角色#
	 */
	public function actionAddrole(){
		$model=new RoleForm();
		$model->scenario="addrole";
		$tableid=0;
		//判断提交
		if(\Yii::$app->request->isPost){
			$model->attributes=\Yii::$app->request->post('RoleForm');//赋值
			$connect=\Yii::$app->db;
			$transaction=$connect->beginTransaction();
			//验证
			if($model->validate()){
				
				//角色表数据写入
				$role=new TauRoleinfo();
				$role->attributes=$model->attributes;	
				try {
					if($role->save()){
						$role->save();
					}else{
						throw new Exception('角色信息写入失败', '1');
					}
					//权限表写入角色数据
					$auth=\Yii::$app->authManager;
					$roleName=$model->RoleName;
					${$roleName}=$auth->createRole($roleName);
					${$roleName}->description=$model->description;
					if($auth->add(${$roleName})){
						$this->redirect(['rbac/addrole']);
					}else{
						throw new Exception('授权角色数据写入失败', '2');
					}
					$transaction->commit();
				} catch (Exception $e) {
					$transaction->rollBack();
				}
			}
		}
		return $this->render('addrole',['model'=>$model,'tableid'=>$tableid]);
	}
	/**
	 * #operation=角色列表#
	 */
	public function actionRolelist(){
		return $this->render('addrole');
	}
	/**
	 * #operation=角色列表异步数据处理#
	 */
	public function actionRoledata(){
		$draw=\Yii::$app->request->post('draw');//获取当前页码
		$start=\Yii::$app->request->post('start');//开始展示条数
		$length=\Yii::$app->request->post('length');//展示条数
		$column=\Yii::$app->request->post('order')[0]['column'];//排序字段
		$order=\Yii::$app->request->post('order')[0]['dir'];//排序方式
		$columnArray=[
			'3'=>'created_at'
		];
		$columnName=$columnArray[$column];
		//查询条件
		if(!empty(\Yii::$app->request->post('search')['value'])){
			$search=\Yii::$app->request->post('search')['value'];
			$where=" and `name` like '%".$search."%'";
		}else{
			$where="";
		}
		//查询角色信息
		$rolemsg=AuthItem::find()->where('type=1'.$where)->orderBy($columnName." ".$order)->offset($start)->limit($length)->asArray()->all();
		//查询角色表总条数
		$rolecount=AuthItem::find()->where('type=1'.$where)->count();
		$data=[];
		foreach($rolemsg as $r){
			
			$dataArray=[];
			$dataArray['checkbox']='<center><label class="pos-rel"><input type="checkbox" class="ace" /><span class="lbl"></span></label></center>';
			$dataArray['rolename']=$r['name'];
			$dataArray['roledescription']=$r['description'];			
			$dataArray['creatat']=date("Y-m-d h:i:s",$r['created_at']);
			$dataArray['options']="<div class=\"hidden-sm hidden-xs action-buttons\">
				<a class=\"blue\" onclick=\"see('".$r['name']."')\">
					<i class=\"ace-icon fa fa-search-plus bigger-130\"></i>
				</a>

				<a class=\"green\" onclick=\"update('".$r['name']."')\">
					<i class=\"ace-icon fa fa-pencil bigger-130\"></i>
				</a>

				<a class=\"red\"  onclick=\"javascript:return show_confirm('".$r['name']."')\">
					<i class=\"ace-icon fa fa-trash-o bigger-130\"></i>
				</a>
			</div>";
			$data[]=$dataArray;			
		}
		$temp=[
			'draw'=>$draw,
			'recordsTotal'=>$rolecount,
			'recordsFiltered'=>$rolecount,
			'data'=>$data
		];
		return json_encode($temp);
	}
	/**
	 * #operation=角色权限查看#
	 */
	public function actionView(){
		//获取post传递的角色名称
		$roleName=\Yii::$app->request->post('name');
		//查询角色下的所有权限
		$rolepermission=AuthItemChild::findAll(['parent'=>$roleName]);
		//获取网站设置模块下边的所有权限
		$setPermission=AuthItem::find()->where("type=2 and name like 'main_%'")->asArray()->all();
		//获取账号管理模块的权限
		$accountPermission=AuthItem::find()->where("type=2 and name like 'operator_%'")->asArray()->all();
		//获取会员管理模块权限
		$memberPermission=AuthItem::find()->where("type=2 and name like 'membermanage_%'")->asArray()->all();
		//获取商品管理模块权限
		$productPermission=AuthItem::find()->where("type=2 and name like 'merchandis_%'")->asArray()->all();
		//获取订单管理模块权限
		$orderPermission=AuthItem::find()->where("type=2 and name like 'order_%'")->asArray()->all();
		//获取库存管理模块权限
		$warePermission=AuthItem::find()->where("type=2 and name like 'purchase_%'")->asArray()->all();
		//获取系统权限模块权限
		$sysPermission=AuthItem::find()->where("type=2 and name like 'rbac_%'")->asArray()->all();
		//获取统计报表模块权限
		$reportPermission=AuthItem::find()->where("type=2 and name like 'report_%'")->asArray()->all();
		
		return $this->renderPartial('_permissionview',[
			'roleName'=>$roleName,
			'rolepermission'=>$rolepermission,
			'setPermission'=>$setPermission,
			'accountPermission'=>$accountPermission,
			'memberPermission'=>$memberPermission,
			'productPermission'=>$productPermission,
			'orderPermission'=>$orderPermission,
			'warePermission'=>$warePermission,
			'sysPermission'=>$sysPermission,
			'reportPermission'=>$reportPermission
		]);
		
	}
	
	/**
	 * #operation=角色权限修改#
	 */
	public function actionPerupdate(){
		$parent=\Yii::$app->request->post('rolename');//获取角色的名称
		$authchild=AuthItemChild::find()->where(['parent'=>$parent])->all();//查找角色的权限名称
		AuthItemChild::deleteAll(['parent'=>$parent]);//删除角色下的全部权限
		$auth=\Yii::$app->authManager;
		$getrole=$auth->getRole($parent);
		$post_key=array_keys($_POST);//获取post传递的key至
		foreach ($post_key as $k){
			if($k != "rolename"){	//获取传递的所有权限名称
				foreach (\Yii::$app->request->post($k) as $r){
					$getoper=$auth->getPermission($r);
					if($auth->addChild($getrole, $getoper)){
						$this->redirect(['rbac/addrole']);
					}else{
						throw new \Exception('添加失败', '404');
					}
				}			
			}
		}
	}
	/**
	 * #operation=角色信息修改#
	 */
	public function actionRoleupdate(){
		//判断是否异步提交
		if(\Yii::$app->request->post('action') && \Yii::$app->request->post('action') == "roleupdate"){
			$postName=\Yii::$app->request->post('name');
			$rolemsg=AuthItem::findOne(['name'=>$postName]);
			$roleState=TauRoleinfo::findOne(['RoleName'=>$postName]);
			$rolemodel=new RoleForm(['scenario'=>'update']);
			\Yii::$app->session->set('rolename',$postName);
			return $this->renderPartial('_roleupdate',[
					'model'=>$rolemodel,
					'name'=>$rolemsg->name,
					'description'=>$rolemsg->description,
					'SortID'=>$roleState->SortID,
					'State'=>$roleState->State
			]);
		}
		
		//判断表单是否提交
		if(\Yii::$app->request->isPost){
			$rolemodel=new RoleForm(['scenario'=>'update']);			
			$rolemodel->attributes=\Yii::$app->request->post('RoleForm');
			if($rolemodel->validate()){
				$oldname=\Yii::$app->session->get('rolename');
				$connect=\Yii::$app->db;
				//禁止修改系统管理员
				if($oldname =="系统管理员" || $oldname =="顶级角色"){
					exit("<script>alert(\"该角色不能修改\");window.history.go(-1);</script>");
				}
				//将要修改的角色变成顶级角色
				$searchOper=TauOperinfo::findAll(['RoleName'=>$oldname]);
				if(!empty($searchOper)){
					if(TauOperinfo::updateAll(['RoleName'=>'顶级角色'],['RoleName'=>$oldname])==0 ){
						throw new \Exception('修改角色为顶级角色失败', '1');
					}
				}
				//将auth_item_child的角色名称变成顶级角色
				$searchparent=AuthItemChild::findAll(['parent'=>$oldname]);
				if(!empty($searchparent)){
					if(AuthItemChild::updateAll(['parent'=>'顶级角色'],['parent'=>$oldname])==0){
						throw new \Exception('修改授权角色为顶级角色失败', '2');
					}
				}
				
				$transaction=$connect->beginTransaction();
				try {
				
					//修改角色信息表的角色
					$roleinfo=TauRoleinfo::findOne(['RoleName'=>$oldname]);
					$roleinfo->RoleName=$rolemodel->RoleName;
					$roleinfo->SortID=$rolemodel->SortID;
					$roleinfo->State=$rolemodel->State;
					if(!$roleinfo->save()){
							
						throw new \Exception('角色信息表角色修改失败', '3');
					}
					//修改操作员角色
					$searchOper=TauOperinfo::findAll(['RoleName'=>'顶级角色']);
				
					if(!empty($searchOper)){
						//将顶级角色改成要修改的角色
						if(TauOperinfo::updateAll(['RoleName'=>$rolemodel->RoleName],['RoleName'=>'顶级角色'])==0){
							throw new \Exception('修改顶级角色失败', '4');
						}
					}
					//修改auth_item_child的角色信息
					$authchild=AuthItemChild::findAll(['parent'=>'顶级角色']);
					if(!empty($authchild)){
						if(AuthItemChild::updateAll(['parent'=>$rolemodel->RoleName],['parent'=>'顶级角色'])==0){
							throw new \Exception('角色授权信息表角色修改失败', '5');
						}
					}
					//查找auth_item的角色
					$authassign=AuthItem::findone(['name'=>$oldname]);
				
					if(!empty($authassign)){
						$authassign->name=$rolemodel->RoleName;
						if(!$authassign->save()){
				
							throw new \Exception('角色权限信息表角色修改失败', '6');
						}
							
					}
				
					//修改auth_assignment角色信息
					$authassign=AuthAssignment::findAll(['item_name'=>$oldname]);
					if(!empty($authassign)){
						if(AuthAssignment::updateAll(['item_name'=>$rolemodel->RoleName],['item_name'=>$oldname])==0){
							throw new \Exception('角色用户授权信息表角色修改失败', '7');
						}
					}
					$transaction->commit();
					$this->redirect(['rbac/addrole']);
				} catch (Exception $e) {
					$transaction->rollBack();
					var_dump($e->getMessage());exit;
				}
			}else{
				//弹出错误提示信息
				$key=array_keys($rolemodel->errors);
				foreach ($key as $k){
					exit("<script>alert(\"".$rolemodel->errors[$k][0]."\");window.history.go(-1);</script>");
				}
			}
		
		}
		
	}
	/**
	 * #operation=角色删除#
	 */
	public function actionRoledelete(){
		if(\Yii::$app->request->post('action') && \Yii::$app->request->post('action') =="delete"){
			$name=\Yii::$app->request->post('name');
			//禁止删除系统管理员角色和顶级角色
			if($name=="系统管理员" || $name=="顶级角色"){
				exit("系统预置，不能修改和删除");
			}
			//查找该角色下是否含有操作员
			$operrole=TauOperinfo::findAll(['RoleName'=>$name]);			
			if(!empty($operrole)){
				exit("该角色被相关操作员引用，不能删除，请先修改操作员岗位再删除");
			}  
			$connect=\Yii::$app->db;
			$transaction=$connect->beginTransaction();
			try {
				$delrole=TauRoleinfo::findOne(['RoleName'=>$name]);		//查找角色表信息
				if(!$delrole->delete()){
					exit('角色删除失败');
				}
				$itemrole=AuthItem::findOne(['name'=>$name]);//查找权限角色标角色
				if($itemrole!=null){
					if(!$itemrole->delete()){
						exit('权限角色删除失败');
					}
				}
				$authchild=AuthItemChild::findAll(['parent'=>$name]);
				if(!empty($authchild)){
					if(AuthItemChild::deleteAll(['parent'=>$name])==0){
						exit('授权角色删除失败');
					}
				}
				$transaction->commit();
				exit('删除成功');
			} catch (Exception $e) {
				$transaction->rollBack();
				var_dump($e->getMessage());
			}
			
		}
	}
	/**
	 * #operation=rbac操作界面#
	 */
	public function actionAddoperation($controllerName='MainController'){
		$controllerMap=$this->getController();
		$operation=$this->getOperaction($controllerName);	
			
		return $this->render('addoperation',[
				'controllerMap'=>$controllerMap,
				'operation'=>$operation
		]);
		
	}
	//获取控制器名和注释
	public function getController(){
		$currentDir=__DIR__;//获取当前文件的路径
		$fileName=scandir($currentDir);//列出当前目录的所有文件
		
		$temp=[];
		
		//遍历目录所有文件重构数组，取出除了.和..其他所有控制器文件名
		foreach ($fileName as $f){
				
			if($f !='.' && $f != '..'){
				$temp[]=substr($f, 0,-4);//去掉.php
			}
				
		}
		$controllerMap=[];
		$n=0;
		//获取控制器名注释
		foreach ($temp as $t){
			
			$fileClass=new \ReflectionClass("backend\controllers\\".$t);//利用php反射机制和yii2的autoload机制
			$classDis=$fileClass->getDocComment();//获取类的注释
			
			preg_match('/#name=(.*.)#/', $classDis,$dis);//替换
			
			$doc[$n]=$dis;
			
			$discription=$doc[$n];
			
			$controllerMap[$n]['description']=$discription[1];
			$controllerMap[$n]['fileName']=$t;
			
			$n++;
		}
		//var_dump($controllerMap);
		return $controllerMap;
	}
	
	//operation=获取控制器所有操作
	public function getOperaction($controllerName){
		$fileClass=new \ReflectionClass("backend\controllers\\".$controllerName);
		
		$methods=$fileClass->getMethods();
		$action=[];
		$i=0;
		foreach($methods as $meth){
			
			$flag=preg_match('/action(.*.)/', $meth->name);
			
			
			if($flag==1 && $meth->name != "actions"){
					
				preg_match('/#operation=(.*.)#/', $meth->getDocComment(),$des);
				
				$methodTrue=substr($meth->name, 6);//字符串截取
				$doc[$i]=$des;
				$description=$doc[$i];

				$action[$i]['methodName']=$methodTrue;
				$action[$i]['description']=$description[1];
				
				$i++;
			}
		}
		return $action;
	}
	/**
	 * #operation=增加权限#
	 */
	public function actionAddpermission(){
		$controllerName=\Yii::$app->request->post('controller');//取出隐藏域传递的控制器名称
		foreach (\Yii::$app->request->post('operation') as $o){
			preg_match('/(.*.)@/', $o,$operation);//正则取出操作名称
			$operationName=$operation[1];
			preg_match('/@(.*.)/', $o,$doc);//取出操作的注释
			$description=$doc[1];			
			$permissionName=$controllerName."_".$operationName;
			$authitem=AuthItem::findOne(['name'=>$permissionName]);
			if($authitem !=null){
				throw new \Exception('权限信息已经存在，请勿重复提交', '404');
			} 
			$auth=\Yii::$app->authManager;
			//添加权限
			${$permissionName}=$auth->createPermission($permissionName);
			//添加权限描述
			${$permissionName}->description=$description;
			//权限写入到数据库
			$result=$auth->add(${$permissionName});
			
		}

			$this->redirect(['rbac/authassign']);
			
	}
	/**
	 * #operation=角色分配模块#
	 */
	public function actionAuthassign($roleName="admin"){
		$roles=AuthItem::find()->where(['type'=>1])->asArray()->all();//获取所有角色
		$controllerName=$this->getController();//获取控制器名称
		
		return $this->render('authassign',[
			'roles'=>$roles,
			'controllerName'=>$controllerName,
		]);
	}
	/**
	 * #operation=角色权限信息写入数据库#
	 */
	public function actionAuthchild(){
		//从表单隐藏域中取出包含的角色信息
		$rolename=\Yii::$app->request->post('rolename');
		//获取角色
		$auth=\Yii::$app->authManager;
		${$rolename}=$auth->getRole($rolename);
		//从表单中获取传递的权限名称
		$permission=\Yii::$app->request->post('permission');
		foreach($permission as $p){
			$permissionName=$auth->getPermission($p);
			$serchp=AuthItemChild::findOne(['parent'=>$rolename,'child'=>$p]);
			if($serchp != null){
				throw new \Exception('角色授权信息已经存在，请勿重复添加', '404');
			}
			$auth->addChild(${$rolename}, $permissionName);
		}
		 $this->redirect(['rbac/authassign']);
	}
	
}

?>